package com.yonyou.pmclouds.statistic.service.rmiimpl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.consts.BillTypeConst;
import com.yonyou.pmclouds.basecom.entity.KeyCountVO;
import com.yonyou.pmclouds.basecom.entity.PageObject;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.util.ChineseStringUtils;
import com.yonyou.pmclouds.basecom.util.DateUtils;
import com.yonyou.pmclouds.organization.entity.OrganizationVO;
import com.yonyou.pmclouds.organization.rmiitf.OrganizationQuery;
import com.yonyou.pmclouds.picture.rmiitf.PicStatistics;
import com.yonyou.pmclouds.project.entity.ProjectBillVO;
import com.yonyou.pmclouds.project.entity.ProjectVO;
import com.yonyou.pmclouds.project.mapper.ProjectBillMapper;
import com.yonyou.pmclouds.project.rmiitf.ProjectSimpleQuery;
import com.yonyou.pmclouds.statistic.entity.*;
import com.yonyou.pmclouds.statistic.rmiitf.ActivityStatisticsService;
import com.yonyou.pmclouds.task.rmiitf.TaskRemoteService;
import com.yonyou.pmclouds.team.entity.TeamEnterpriseVO;
import com.yonyou.pmclouds.team.entity.TeamMemberVO;
import com.yonyou.pmclouds.team.rmiitf.TeamEnterpriseQuery;
import com.yonyou.pmclouds.team.rmiitf.TeamMemberQuery;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = ActivityStatisticsService.class, timeout = 5000)
public class ActivityStatisticsServiceImpl implements ActivityStatisticsService {
    public static final String[] EXCLUDE_BILL_TYPE = {BillTypeConst.SIGN_IN_BILLTYPE, BillTypeConst.PROCESS_PLAN_BILLTYPE, BillTypeConst.PROCESS_REPORT_BILLTYPE};
    public static final String[] NO_STATUS_BILL_TYPE = {BillTypeConst.WORKCONNECT_BILLTYPE, BillTypeConst.PARALLEL_INSPECTION_BILLTYPE,
            BillTypeConst.SIDE_INSPECTION_BILLTYPE, BillTypeConst.PATROL_BILLTYPE, BillTypeConst.PROBLEMLOG_BILLTYPE, BillTypeConst.SAFETY_RECTIFICATION_BILLTYPE,BillTypeConst.WORKSTOP_BILLTYPE,
            BillTypeConst.STAGECHECK_BILLTYPE};
    @Autowired
    private PicStatistics picStatistics;
    @Autowired
    private TaskRemoteService taskService;
    @Autowired
    private ProjectBillMapper billMapper;
    @Autowired
    private ProjectSimpleQuery projectQuery;
    @Autowired
    private TeamMemberQuery teamMemberQuery;
    @Autowired
    private TeamEnterpriseQuery teamEnterpriseQuery;
    @Autowired
    private OrganizationQuery orgQuery;

    @Override
    public OrgActivityStatisticsViewVOs queryActivityInfo(String tenantId, String orgId, int limit, long timeStart, long timeEnd) throws BusinessException {
        String[] projects = projectQuery.queryProjectIdByTenantOrg(null, tenantId, orgId);
        if (ArrayUtils.isEmpty(projects)) {
            return new OrgActivityStatisticsViewVOs(null, 0, 0);
        }
        Date start = DateUtils.asDateBegin(new Date(timeStart));
        Date end = DateUtils.asDateEnd(new Date(timeEnd));
        //  统计单据数量
        int billCount = billMapper.countBillCountExcludeType(projects, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, start, end);
        //  统计图片数量
        int picCount = picStatistics.queryPicCountByProjects(projects, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, start, end);
        // 项目单据数排行
        OrgActivityStatisticVO[] orders = null;
        if (limit > 0) {
            KeyCountVO[] keyCountVOS = billMapper.countProjectBillCountExcludeType(projects, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, start, end, 0, limit);
            // 转换keycount
            if (ArrayUtils.isNotEmpty(keyCountVOS)) {
                String[] ids = new String[keyCountVOS.length];
                for (int i = 0; i < keyCountVOS.length; i++) {
                    ids[i] = keyCountVOS[i].getRelateKey();
                }
                Map<String, Integer> picCounts = picStatistics.queryPicCountOfPerProjects(ids, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, start, end);

                Map<String, ProjectVO> projectMap = projectQuery.queryProjects(ids);
                orders = new OrgActivityStatisticVO[keyCountVOS.length];
                for (int i = 0; i < keyCountVOS.length; i++) {
                    orders[i] = new OrgActivityStatisticVO();
                    orders[i].setCount(keyCountVOS[i].getKeyNum() == null ? 0 : keyCountVOS[i].getKeyNum());
                    orders[i].setPkProject(keyCountVOS[i].getRelateKey());
                    ProjectVO projectVO = projectMap.get(keyCountVOS[i].getRelateKey());
                    if (projectVO != null) {
                        orders[i].setProjectName(projectVO.getSname());
                        orders[i].setProjectManager(projectVO.getManager());
                    }
                    if (picCounts != null) {
                        Integer projectPicCount = picCounts.get(keyCountVOS[i].getRelateKey());
                        orders[i].setPicCount(projectPicCount == null ? 0 : projectPicCount);
                    } else {
                        orders[i].setPicCount(0);
                    }
                    orders[i].setSeq(i);
                }
            }
        }
        return new OrgActivityStatisticsViewVOs(orders, billCount, picCount);
    }

    @Override
    public PageObject<?> queryOrgActivityOrder(String tenantId, String orgWord, int start, int limit, long timeStart, long timeEnd) throws BusinessException {
        // search org
        OrganizationVO[] orgVos = orgQuery.queryOrgListByTenantWithKeyword(tenantId, orgWord);
        if (ArrayUtils.isEmpty(orgVos)) {
            return null;
        }
        // Plain the org tree
        List<OrganizationVO> orgList = new ArrayList<>(Arrays.asList(orgVos));
        Map<String, String> pkNameOrg = new HashMap<>();
        int i = 0;
        while (i < orgList.size()) {
            OrganizationVO org = orgList.get(i);
            pkNameOrg.put(org.getPkSrc(), org.getSname());
            i++;
            if (!ArrayUtils.isEmpty(org.getChildren())) {
                orgList.addAll(Arrays.asList(org.getChildren()));
            }
        }
        if (StringUtils.isEmpty(orgWord)) {
            // 添加租户的筛选
            pkNameOrg.put(null, null);
        }
        Date startDate = DateUtils.asDateBegin(new Date(timeStart));
        Date endDate = DateUtils.asDateEnd(new Date(timeEnd));
        // get project by org
        Map<String, List<ProjectVO>> projectOrgs
                = projectQuery.queryProjectsByOrgs(tenantId, pkNameOrg.keySet().toArray(new String[0]));
        if (projectOrgs == null || projectOrgs.isEmpty()) {
            return null;
        }
        List<TenantActivityStatisticVO> result = new ArrayList<>(projectOrgs.size());
        for (Map.Entry<String, List<ProjectVO>> entry : projectOrgs.entrySet()) {
            List<ProjectVO> projects = entry.getValue();
            if (projects == null || projects.isEmpty()) {
                continue;
            }
            List<String> pkProjectList = new ArrayList<>(projectOrgs.size());
            for (ProjectVO project : projects) {
                pkProjectList.add(project.getPkProject());
            }
            String[] pkProjects = pkProjectList.toArray(new String[0]);
            int billCount = billMapper.countBillCountExcludeType(pkProjects, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, startDate, endDate);
            int picCount = picStatistics.queryPicCountByProjects(pkProjects, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, startDate, endDate);

            TenantActivityStatisticVO statistic = new TenantActivityStatisticVO();
            statistic.setBillCount(billCount);
            statistic.setPicCount(picCount);
            statistic.setOrgName(pkNameOrg.get(entry.getKey()));
            statistic.setPkOrg(entry.getKey());
            statistic.setSeq(0);
            result.add(statistic);
        }
        // sort
        Collections.sort(result, new Comparator<TenantActivityStatisticVO>() {
            @Override
            public int compare(TenantActivityStatisticVO o1, TenantActivityStatisticVO o2) {
                if (o1 == o2) {
                    return 0;
                }
                int billCount = o1.getBillCount() - o2.getBillCount();
                if (billCount != 0) {
                    return -billCount;
                }
                int picCount = o1.getPicCount() - o2.getPicCount();
                if (picCount != 0) {
                    return -picCount;
                }
                return ChineseStringUtils.compareInDict(o1.getOrgName(), o2.getOrgName());
            }
        });
        List<TenantActivityStatisticVO> finalResult = result.subList(start, Math.min(start + limit, result.size()));
        for (int j = 0; j < finalResult.size(); j++) {
            TenantActivityStatisticVO statistic = finalResult.get(j);
            statistic.setSeq(j);
        }
        return new PageObject<>(finalResult.toArray(new TenantActivityStatisticVO[0]), result.size(), start);
    }

    @Override
    public OrgActivityStatisticsViewVOs queryTenantActivityInfo(String tenantId, long timeStart, long timeEnd) throws BusinessException {
        return this.queryActivityInfo(tenantId, null, 0, timeStart, timeEnd);
    }

    @Override
    public PageObject<?> queryProjectActivityOrder(String tenantId, String orgId, String keyWord, int start, int limit, long timeStart, long timeEnd) throws BusinessException {
        String[] projects = projectQuery.queryProjectIdByTenantOrg(keyWord, tenantId, orgId);
        Date startDate = DateUtils.asDateBegin(new Date(timeStart));
        Date endDate = DateUtils.asDateEnd(new Date(timeEnd));
        // 项目单据数排行
        KeyCountVO[] keyCountVOS = billMapper.countProjectBillCountExcludeType(projects, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, startDate, endDate, start, limit);
        OrgActivityStatisticVO[] orders = null;
        // 转换keycount
        if (ArrayUtils.isNotEmpty(keyCountVOS)) {
            String[] ids = new String[keyCountVOS.length];
            for (int i = 0; i < keyCountVOS.length; i++) {
                ids[i] = keyCountVOS[i].getRelateKey();
            }
            Map<String, Integer> picCounts = picStatistics.queryPicCountOfPerProjects(ids, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, startDate, endDate);
            Map<String, ProjectVO> projectMap = projectQuery.queryProjects(ids);
            orders = new OrgActivityStatisticVO[keyCountVOS.length];
            for (int i = 0; i < keyCountVOS.length; i++) {
                orders[i] = new OrgActivityStatisticVO();
                orders[i].setCount(keyCountVOS[i].getKeyNum() == null ? 0 : keyCountVOS[i].getKeyNum());
                orders[i].setPkProject(keyCountVOS[i].getRelateKey());
                ProjectVO projectVO = projectMap.get(keyCountVOS[i].getRelateKey());
                if (projectVO != null) {
                    orders[i].setProjectName(projectVO.getSname());
                    orders[i].setProjectManager(projectVO.getManager());
                }
                if (picCounts != null) {
                    Integer projectPicCount = picCounts.get(keyCountVOS[i].getRelateKey());
                    orders[i].setPicCount(projectPicCount == null ? 0 : projectPicCount);
                }
                orders[i].setSeq(i);
            }
        }
        return new PageObject<>(orders, projects.length, start);
    }

    @Override
    public ProjectBillTypeCountVO[] queryCountOfProjectBillType(String tenantId, String pkProject, long timeStart, long timeEnd) {
        Date startDate = DateUtils.asDateBegin(new Date(timeStart));
        Date endDate = DateUtils.asDateEnd(new Date(timeEnd));
        KeyCountVO[] billCounts = billMapper.queryBillTypeCountExcludeType(pkProject, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, startDate, endDate);
        if (ArrayUtils.isEmpty(billCounts)) {
            return null;
        }
        Map<String, Integer> picTypeCount = picStatistics.queryCountOfBillType(tenantId, pkProject, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, startDate, endDate);
        List<ProjectBillTypeCountVO> result = new ArrayList<>();
        for (KeyCountVO keyCount : billCounts) {
            ProjectBillTypeCountVO tmp = new ProjectBillTypeCountVO();
            Integer keyNum = keyCount.getKeyNum();
            tmp.setBillCount(keyNum == null ? 0 : keyNum);
            if (picTypeCount != null) {
                Integer picCount = picTypeCount.get(keyCount.getRelateKey());
                tmp.setPicCount(picCount == null ? 0 : picCount);
            }
            tmp.setBillType(keyCount.getRelateKey());
            result.add(tmp);
        }
        return result.toArray(new ProjectBillTypeCountVO[0]);
    }

    @Override
    public ActivityPenetrateVO queryActivityDetail(String tenantId, String orgId, long timeStart, long timeEnd) throws BusinessException {
        String[] projects = projectQuery.queryProjectIdByTenantOrg(null, tenantId, orgId);
        if (ArrayUtils.isEmpty(projects)) return new ActivityPenetrateVO();

        Date start = DateUtils.asDateBegin(new Date(timeStart));
        Date end = DateUtils.asDateEnd(new Date(timeEnd));
        //  查询项目下单据
        ProjectBillVO[] projectBillVOS = billMapper.queryBillCountExcludeType(projects, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, start, end);
        if (projectBillVOS == null || projectBillVOS.length == 0) return new ActivityPenetrateVO();

        Map<String, Integer> billCountMap = new HashMap<>();
        for (ProjectBillVO billVO : projectBillVOS) {
            String billkey = billVO.getPkProject() + billVO.getCreator();
            billCountMap.put(billkey, billVO.getBillNum());
        }

        TeamMemberVO[] teamMemberVOS = teamMemberQuery.queryByprojects(projects);
        Map<Byte, Integer> roleNumMap = new HashMap<>();//角色单据数
        Map<String, Integer> constructMap = new HashMap<>();//施工企业单据数
        Map<String, Integer> supervisorMap = new HashMap<>();//监理企业单据数
        Map<String, Integer> ownEntMap = new HashMap<>();//甲方企业单据数
        Map<String, Integer> ownerMap = new HashMap<>();//甲方人员单据数
        Map<String, Integer> managerEntMap = new HashMap<>();//项目经理企业单据数
        Map<String, String> managerMap = new HashMap<>();//项目经理人员
        Set<String> enterpriseIdSet = new HashSet<>();
        for (TeamMemberVO teamMemberVO : teamMemberVOS) {
            String memberKey = teamMemberVO.getPkProject() + teamMemberVO.getPkUser();
            int billNum = billCountMap.get(memberKey) == null ? 0 : billCountMap.get(memberKey);
            if (TeamMemberVO.UserRoleConst.ROLE_MANAGER == teamMemberVO.getUserRole()) {
                String entKey = teamMemberVO.getPkProject() + teamMemberVO.getPkEnterprise();
                if (managerEntMap.get(entKey) == null) managerEntMap.put(entKey, 0);
                managerEntMap.put(entKey, managerEntMap.get(entKey) + billNum);
                enterpriseIdSet.add(teamMemberVO.getPkEnterprise());
                managerMap.put(entKey, teamMemberVO.getPkUser());
            } else {
                if (roleNumMap.get(teamMemberVO.getUserRole()) == null) {
                    roleNumMap.put(teamMemberVO.getUserRole(), 0);
                }
                roleNumMap.put(teamMemberVO.getUserRole(), roleNumMap.get(teamMemberVO.getUserRole()) + billNum);
            }

            if (TeamMemberVO.UserRoleConst.ROLE_CONSTRUCTOR == teamMemberVO.getUserRole()) {
                if (constructMap.get(teamMemberVO.getPkEnterprise()) == null) {
                    constructMap.put(teamMemberVO.getPkEnterprise(), 0);
                }
                constructMap.put(teamMemberVO.getPkEnterprise(), constructMap.get(teamMemberVO.getPkEnterprise()) + billNum);
            }

            if (TeamMemberVO.UserRoleConst.ROLE_SUPERVISOR == teamMemberVO.getUserRole()) {
                if (supervisorMap.get(teamMemberVO.getPkEnterprise()) == null) {
                    supervisorMap.put(teamMemberVO.getPkEnterprise(), 0);
                }
                supervisorMap.put(teamMemberVO.getPkEnterprise(), supervisorMap.get(teamMemberVO.getPkEnterprise()) + billNum);
            }

            if (TeamMemberVO.UserRoleConst.ROLE_OWNER == teamMemberVO.getUserRole()) {
                if (ownerMap.get(teamMemberVO.getPkUser()) == null) {
                    ownerMap.put(teamMemberVO.getPkUser(), 0);
                }
                ownerMap.put(teamMemberVO.getPkUser(), ownerMap.get(teamMemberVO.getPkUser()) + billNum);
                if (ownEntMap.get(teamMemberVO.getPkEnterprise()) == null) {
                    ownEntMap.put(teamMemberVO.getPkEnterprise(), 0);
                }
                ownEntMap.put(teamMemberVO.getPkEnterprise(), ownEntMap.get(teamMemberVO.getPkEnterprise()) + billNum);

            }
        }
        //项目经理角色区分
        if (!enterpriseIdSet.isEmpty()) {
            TeamEnterpriseVO[] teamEnterpriseVOS = teamEnterpriseQuery.queryByPkEnts(enterpriseIdSet.toArray(new String[0]));
            for (TeamEnterpriseVO enterpriseVO : teamEnterpriseVOS) {
                String enterpriseKey = enterpriseVO.getPkProject() + enterpriseVO.getPkEnterprise();
                if (managerEntMap.get(enterpriseKey) != null) {
                    roleNumMap.put(enterpriseVO.getEntRole(), (roleNumMap.get(enterpriseVO.getEntRole()) == null ? 0 : roleNumMap.get(enterpriseVO.getEntRole())) + managerEntMap.get(enterpriseKey));
                    if (TeamMemberVO.UserRoleConst.ROLE_CONSTRUCTOR == enterpriseVO.getEntRole()) {
                        constructMap.put(enterpriseVO.getPkEnterprise(), (constructMap.get(enterpriseVO.getPkEnterprise()) == null ? 0 : constructMap.get(enterpriseVO.getPkEnterprise())) + managerEntMap.get(enterpriseKey));
                    }
                    if (TeamMemberVO.UserRoleConst.ROLE_SUPERVISOR == enterpriseVO.getEntRole()) {
                        supervisorMap.put(enterpriseVO.getPkEnterprise(), (supervisorMap.get(enterpriseVO.getPkEnterprise()) == null ? 0 : supervisorMap.get(enterpriseVO.getPkEnterprise())) + managerEntMap.get(enterpriseKey));
                    }
                    if (TeamMemberVO.UserRoleConst.ROLE_OWNER == enterpriseVO.getEntRole()) {
                        String pkUser = managerMap.get(enterpriseKey);
                        if (ownerMap.get(pkUser) == null) ownerMap.put(pkUser, 0);
                        ownerMap.put(pkUser, ownerMap.get(pkUser) + managerEntMap.get(enterpriseKey));
                        if (ownEntMap.get(enterpriseVO.getPkEnterprise()) == null) {
                            ownEntMap.put(enterpriseVO.getPkEnterprise(), 0);
                        }
                        ownEntMap.put(enterpriseVO.getPkEnterprise(), ownEntMap.get(enterpriseVO.getPkEnterprise()) + managerEntMap.get(enterpriseKey));
                    }
                }
            }
        }

        ActivityPenetrateVO activityPenetrateVO = new ActivityPenetrateVO();
        //各角色单据数统计
        int billCount = 0;
        for (Byte key : roleNumMap.keySet()) {
            if (TeamMemberVO.UserRoleConst.ROLE_OWNER == key) {
                activityPenetrateVO.setOwnerBillCount(activityPenetrateVO.getOwnerBillCount() + roleNumMap.get(key));
            } else if (TeamMemberVO.UserRoleConst.ROLE_CONSTRUCTOR == key) {
                activityPenetrateVO.setConstructionBillCount(activityPenetrateVO.getConstructionBillCount() + roleNumMap.get(key));
            } else if (TeamMemberVO.UserRoleConst.ROLE_SUPERVISOR == key) {
                activityPenetrateVO.setSupervisionBillCount(activityPenetrateVO.getSupervisionBillCount() + roleNumMap.get(key));
            }
            billCount += roleNumMap.get(key);
        }
        activityPenetrateVO.setBillCount(billCount);
        //各角色单据列表
        List<ActivityCountVO> constructCountList = convertMap(constructMap);
        List<ActivityCountVO> supervisorCountList = convertMap(supervisorMap);
        List<ActivityCountVO> ownerCountList = convertMap(ownerMap);
        List<ActivityCountVO> ownEntCountList = convertMap(ownEntMap);
        //施工企业单据列表
        if (!constructCountList.isEmpty()) activityPenetrateVO.setConstructCountList(constructCountList);
        //监理企业单据列表
        if (!supervisorCountList.isEmpty()) activityPenetrateVO.setSupervisorCountList(supervisorCountList);
        //甲方人员单据列表
        if (!ownerCountList.isEmpty()) activityPenetrateVO.setOwnerCountList(ownerCountList);
        //甲方企业单据列表
        if (!ownEntCountList.isEmpty()) activityPenetrateVO.setOwnEntCountList(ownEntCountList);
        return activityPenetrateVO;
    }

    @Override
    public MemberCountVO[] queryEntPersonRankInOrg(String tenantId, String orgId, String entId,
                                                   long timeStart, long timeEnd, Integer pageStart, Integer limit) throws BusinessException {
        // 获取组织项目列表
        Map<String, List<ProjectVO>> orgProjectMap = projectQuery.queryProjectsByOrgs(tenantId, new String[]{orgId});
        if (orgProjectMap == null) {
            return new MemberCountVO[0];
        }
        List<ProjectVO> orgProjects = orgProjectMap.get(orgId);
        if (orgProjects == null || orgProjects.isEmpty()) {
            return new MemberCountVO[0];
        }
        Date start = DateUtils.asDateBegin(new Date(timeStart));
        Date end = DateUtils.asDateEnd(new Date(timeEnd));
        List<String> projectIds = new ArrayList<>(orgProjects.size());
        Map<String, ProjectVO> projectVOMap = new HashMap<>(orgProjects.size());
        for (ProjectVO orgProject : orgProjects) {
            projectIds.add(orgProject.getPkProject());
            projectVOMap.put(orgProject.getPkProject(), orgProject);
        }
        String[] ids = projectIds.toArray(new String[0]);
        // 项目团队列表
        TeamMemberVO[] teamMemberVOS = teamMemberQuery.queryByprojects(ids);
        if (ArrayUtils.isEmpty(teamMemberVOS)) {
            return new MemberCountVO[0];
        }
        Set<String> memberIds = new HashSet<>();
        List<TeamMemberVO> members = new ArrayList<>();
        for (TeamMemberVO memberVO : teamMemberVOS) {
            if (entId.equals(memberVO.getPkEnterprise())) {
                members.add(memberVO);
                memberIds.add(memberVO.getPkUser());
            }
        }

        List<ProjectBillVO> projectBillVOs = queryByCreatorOfProjects(teamMemberVOS, memberIds.toArray(new String[0]), projectIds.toArray(new String[0]),
                start, end);
        KeyCountVO[] memberCounts = calculateBillCountOfUser(projectBillVOs);
//        KeyCountVO[] memberCounts = billMapper.countByMemberInProjects(memberIds.toArray(new String[0]), projectIds.toArray(new String[0]),
//                EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, start, end);
        MemberCountVO[] result = new MemberCountVO[memberIds.size()];
        Map<String, MemberCountVO> memberCountVOMap = new HashMap<>(memberIds.size());
        Set<String> noBillMemberIds = new HashSet<>(memberIds);
        for (int i = 0; i < memberCounts.length; i++) {
            result[i] = new MemberCountVO();
            result[i].setMemberId(memberCounts[i].getRelateKey());
            result[i].setBillCount(memberCounts[i].getKeyNum());
            noBillMemberIds.remove(memberCounts[i].getRelateKey());
            memberCountVOMap.put(memberCounts[i].getRelateKey(), result[i]);
        }
        //fillPersonProject(start, end, projectVOMap, members.toArray(new TeamMemberVO[0]), memberCountVOMap);
        fill(start, end, projectVOMap, projectBillVOs, memberCountVOMap);
        String[] noBillMembers = noBillMemberIds.toArray(new String[0]);
        //  补零
        for (int i = memberCounts.length; i < result.length; i++) {
            result[i] = new MemberCountVO();
            result[i].setMemberId(noBillMembers[i - memberCounts.length]);
            result[i].setBillCount(0);
        }

        return result;
    }

    /**
     * 统计用户的制单数
     *
     * @param projectBillVOs
     * @return
     */
    private KeyCountVO[] calculateBillCountOfUser(List<ProjectBillVO> projectBillVOs) {
        Map<String, KeyCountVO> result = new HashMap<>();
        if (CollectionUtils.isEmpty(projectBillVOs))
            return new KeyCountVO[0];

        String user;
        KeyCountVO currVO;
        for (ProjectBillVO billVO : projectBillVOs) {
            user = billVO.getCreator();
            currVO = result.get(user);
            if (currVO == null) {
                KeyCountVO countVO = new KeyCountVO();
                countVO.setRelateKey(user);
                countVO.setKeyNum(1);
                result.put(user, countVO);
            } else {
                currVO.setKeyNum(currVO.getKeyNum() + 1);
            }
        }

        return result.values().toArray(new KeyCountVO[0]);
    }

    /**
     * 根据用户和项目查询单据，并根据团队成员进行过滤
     *
     * @param teamMemberVOS
     * @param userIds
     * @param projectIds
     * @return
     */
    private List<ProjectBillVO> queryByCreatorOfProjects(TeamMemberVO[] teamMemberVOS, String[] userIds, String[] projectIds,
                                                         Date start, Date end) {
        List<ProjectBillVO> result = new ArrayList<>();
        List<ProjectBillVO> projectBillVOs = billMapper.queryByCreatorOfProjects(userIds, projectIds, EXCLUDE_BILL_TYPE,
                NO_STATUS_BILL_TYPE, start, end);

        // key: 用户，value:用户做过的项目pk集合
        Map<String, Set<String>> userToProjectMap = new HashMap<>();
        for (TeamMemberVO vo : teamMemberVOS) {
            if (userToProjectMap.get(vo.getPkUser()) == null) {
                userToProjectMap.put(vo.getPkUser(), new HashSet<String>());
            }

            userToProjectMap.get(vo.getPkUser()).add(vo.getPkProject());
        }

        String creator2, pkProject;
        for (ProjectBillVO billVO : projectBillVOs) {
            creator2 = billVO.getCreator();
            pkProject = billVO.getPkProject();
            if (!userToProjectMap.containsKey(creator2))
                continue;

            if (!userToProjectMap.get(creator2).contains(pkProject))
                continue;

            result.add(billVO);
        }

        return result;
    }

    private void fill(Date start, Date end, Map<String, ProjectVO> projectVOMap, List<ProjectBillVO> projectBillVOS,
                      Map<String, MemberCountVO> memberCountVOMap) {
        if (CollectionUtils.isEmpty(projectBillVOS) || MapUtils.isEmpty(projectVOMap))
            return;

        // key: 用户 + "!" + 项目，value：KeyCountVO
        Map<String, KeyCountVO> countMap = new HashMap<>();
        String creator2, pkProject;
        KeyCountVO currCountVO;
        for (ProjectBillVO billVO : projectBillVOS) {
            creator2 = billVO.getCreator();
            pkProject = billVO.getPkProject();

            currCountVO = countMap.get(creator2 + "!" + pkProject);
            if (currCountVO == null) {
                KeyCountVO newCount = new KeyCountVO();
                newCount.setRelateKey(creator2 + "!" + pkProject);
                newCount.setKeyNum(1);
                countMap.put(creator2 + "!" + pkProject, newCount);
            } else {
                currCountVO.setKeyNum(currCountVO.getKeyNum() + 1);
            }
        }

        // 填充项目信息
        for (KeyCountVO memberProjectCount : countMap.values().toArray(new KeyCountVO[0])) {
            String relateKey = memberProjectCount.getRelateKey();
            int split = relateKey.indexOf('!');
            String creator = relateKey.substring(0, split);
            String project = relateKey.substring(split + 1);
            MemberCountVO memberCountVO = memberCountVOMap.get(creator);
            if (memberCountVO == null) {
                continue;
            }
            List<MemberCountVO.ProjectCount> projectCounts = memberCountVO.getProjectCounts();
            if (projectCounts == null) {
                projectCounts = new ArrayList<>();
                memberCountVO.setProjectCounts(projectCounts);
            }
            MemberCountVO.ProjectCount count = new MemberCountVO.ProjectCount();
            count.setProjectId(project);
            count.setBillCount(memberProjectCount.getKeyNum());
            count.setProjectName(projectVOMap.get(project).getSname());
            projectCounts.add(count);
        }
    }

    private void fillPersonProject(Date start, Date end, Map<String, ProjectVO> projectVOMap, TeamMemberVO[] teamMemberVOS, Map<String, MemberCountVO> memberCountVOMap) {
        KeyCountVO[] memberProjectCounts = billMapper.countByProjectTeamMember(teamMemberVOS, EXCLUDE_BILL_TYPE, NO_STATUS_BILL_TYPE, start, end);
        // 填充项目信息
        for (KeyCountVO memberProjectCount : memberProjectCounts) {
            String relateKey = memberProjectCount.getRelateKey();
            int split = relateKey.indexOf('!');
            String creator = relateKey.substring(0, split);
            String project = relateKey.substring(split + 1);
            MemberCountVO memberCountVO = memberCountVOMap.get(creator);
            if (memberCountVO == null) {
                continue;
            }
            List<MemberCountVO.ProjectCount> projectCounts = memberCountVO.getProjectCounts();
            if (projectCounts == null) {
                projectCounts = new ArrayList<>();
                memberCountVO.setProjectCounts(projectCounts);
            }
            MemberCountVO.ProjectCount count = new MemberCountVO.ProjectCount();
            count.setProjectId(project);
            count.setBillCount(memberProjectCount.getKeyNum());
            count.setProjectName(projectVOMap.get(project).getSname());
            projectCounts.add(count);
        }
    }

    private List<ActivityCountVO> convertMap(Map<String, Integer> activityMap) {
        List<ActivityCountVO> activityCountList = new ArrayList<>();
        for (String pkActivity : activityMap.keySet()) {
            ActivityCountVO entCountVO = new ActivityCountVO();
            entCountVO.setPkActivity(pkActivity);
            entCountVO.setBillCount(activityMap.get(pkActivity));
            activityCountList.add(entCountVO);
        }
        Collections.sort(activityCountList);
        return activityCountList;
    }
}
